package grpc

import (
	"context"
	"fmt"
	"log"
	"os"

	authpb "e-commerce/services/auth-service/api/pb"
	pb "e-commerce/services/product-service/api/pb"
	"e-commerce/services/product-service/internal/service"

	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
	"gopkg.in/yaml.v3"
)

type ProductServer struct {
	pb.UnimplementedProductServiceServer
	ProductService *service.ProductService
	AuthClient     *AuthClient
}

type AuthClient struct {
	client authpb.AuthServiceClient
	conn   *grpc.ClientConn
}

type contextKey string

const (
	userIDKey contextKey = "user_id"
	roleKey   contextKey = "role"
)

func NewProductServer(configPath string) *ProductServer {
	productService := service.NewProductService(configPath)
	authClient, err := NewAuthClient(configPath)
	if err != nil {
		log.Fatalf("failed to create auth service: %v", err)
	}
	return &ProductServer{
		ProductService: productService,
		AuthClient:     authClient,
	}
}

type Config struct {
	AuthService auth_service `yaml:"auth_service"`
}

type auth_service struct {
	Addr string `yaml:"addr"`
}

func NewAuthClient(configPath string) (*AuthClient, error) {
	yamlFile, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %v", err)
	}
	var config Config
	err = yaml.Unmarshal(yamlFile, &config)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal config file: %v", err)
	}
	conn, err := grpc.NewClient(
		config.AuthService.Addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
	)
	if err != nil {
		return nil, fmt.Errorf("failed to create auth service client: %v", err)
	}
	authClient := &AuthClient{
		client: authpb.NewAuthServiceClient(conn),
		conn:   conn,
	}
	return authClient, nil
}

func (c *AuthClient) Close() error {
	if c.conn != nil {
		return c.conn.Close()
	}
	return nil
}

// 获取单个商品
func (s *ProductServer) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.GetProductResponse, error) {
	product, err := s.ProductService.GetProductByID(req.Id)
	if err != nil {
		return nil, err
	}
	return &pb.GetProductResponse{Product: product}, nil
}

// 创建商品
func (s *ProductServer) CreateProduct(ctx context.Context, req *pb.CreateProductRequest) (*pb.CreateProductResponse, error) {
	id, err := s.ProductService.CreateProduct(req.Product)
	if err != nil {
		return nil, err
	}
	return &pb.CreateProductResponse{Id: id}, nil
}

// 更新商品
func (s *ProductServer) UpdateProduct(ctx context.Context, req *pb.UpdateProductRequest) (*pb.UpdateProductResponse, error) {
	err := s.ProductService.UpdateProduct(req.Product.Id, req.Product)
	if err != nil {
		return nil, err
	}
	return &pb.UpdateProductResponse{Success: true}, nil
}

// 删除商品
func (s *ProductServer) DeleteProduct(ctx context.Context, req *pb.DeleteProductRequest) (*pb.DeleteProductResponse, error) {
	err := s.ProductService.DeleteProduct(req.Id)
	if err != nil {
		return nil, err
	}
	return &pb.DeleteProductResponse{Success: true}, nil
}

// 获取商品列表
func (s *ProductServer) ListProducts(ctx context.Context, req *pb.ListProductsRequest) (*pb.ListProductsResponse, error) {
	products, err := s.ProductService.ListProducts(req.Category)
	if err != nil {
		return nil, err
	}

	return &pb.ListProductsResponse{Products: products}, nil
}

// 添加token认证中间件
func (s *ProductServer) AuthMiddleware(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
	// defer s.AuthClient.Close()
	//从metadata中获取token
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, status.Error(codes.Unauthenticated, "token is required")
	}
	tokens := md.Get("authorization")
	if len(tokens) == 0 {
		return nil, status.Error(codes.Unauthenticated, "token is required")
	}
	token := tokens[0]
	log.Println("token:", token)
	// 调用 auth-service 验证 token
	validateResp, err := s.AuthClient.client.ValidateToken(ctx, &authpb.ValidateTokenRequest{
		Token: token,
	})
	if err != nil {
		return nil, status.Error(codes.Unauthenticated, err.Error())
	}

	if !validateResp.Valid {
		return nil, status.Error(codes.Unauthenticated, "invalid token")
	}

	// 将用户信息添加到上下文
	newCtx := context.WithValue(ctx, userIDKey, validateResp.UserId)
	newCtx = context.WithValue(newCtx, roleKey, validateResp.Role)

	// 调用实际的处理函数
	return handler(newCtx, req)

}

// // 工具函数：将模型转换为 gRPC 结构体
// func convertToProto(product *models.Product) *pb.Product {
// 	return &pb.Product{
// 		Id:          product.ID.Hex(),
// 		Name:        product.Name,
// 		Description: product.Description,
// 		Price:       product.Price,
// 		Stock:       product.Stock,
// 		Category:    product.Category,
// 	}
// }
